from j264.tools import attributes
from j264.tools.boxes.AttributedObject import AttributedObject
from j264.tools.boxes.Connection import Connection
import copy


class Box(AttributedObject):

    ### INITIALIZER ###

    def __init__(self, inlet_count=0, outlet_count=0):
        assert 0 <= inlet_count
        assert 0 <= outlet_count

        AttributedObject.__init__(self)

        self._box_attributes = { }
        self._connections = []
        self._id = 1
        self._inlet_count = int(inlet_count)
        self._outlet_count = int(outlet_count)
        self._parent = None

        self.patching_rect = (0, 0, 100, 20)

    ### READ-ONLY PUBLIC PROPERTIES ###

    @property
    def connections(self):
        return tuple(self._connections)

    @property
    def inlet_count(self):
        return self._inlet_count

    @property
    def outlet_count(self):
        return self._outlet_count

    @property
    def max_obj_id(self):
        return "obj-{}".format(self._id)

    @property
    def max_obj_type(self):
        return 'box'

    @property
    def patcher(self):
        return self._parent

    @property
    def root_patcher(self):
        node = self
        while hasattr(node, 'patcher'):
            node = node.patcher
        return node

    ### READ/WRITE PUBLIC ATTRIBUTES ###

    @attributes.SymbolAttribute()
    def annotation(self):
        return ''

    @attributes.BooleanAttribute()
    def background(self):
        return False

    @attributes.ColorAttribute()
    def color(self):
        return (0, 0, 0, 1)

    @attributes.IntAttribute(minimum=0, maximum=2)
    def fontface(self):
        return 0

    @attributes.SymbolAttribute()
    def fontname(self):
        return 'Arial'

    @attributes.FloatAttribute(minimum=0)
    def fontsize(self):
        return 12.

    @attributes.BooleanAttribute()
    def hidden(self):
        return False

    @attributes.SymbolAttribute()
    def hint(self):
        return ''

    @attributes.BooleanAttribute()
    def ignoreclick(self):
        return False

    @attributes.DimensionAttribute()
    def patching_rect(self):
        return (0, 0, 100, 20)

    @attributes.BooleanAttribute()
    def presentation(self):
        return False

    @attributes.DimensionAttribute()
    def presentation_rect(self):
        return (0, 0, 100, 20)

    @attributes.ColorAttribute()
    def textcolor(self):
        return (0, 0, 0, 1)

    @attributes.SymbolAttribute()
    def varname(self):
        return ''

    ### PRIVATE METHODS ###

    def _get_json_data(self):
        attrs = copy.copy(self._box_attributes)
        attrs['id'] = self.max_obj_id
        return {self.max_obj_type: attrs}

    def _switch_parent(self, new_parent):
        if self._parent is not None:
            index = self._parent.index(self)
            self._parent._children.pop(index)
        self._parent = new_parent
        for connection in self.connections:
            self.disconnect(connection)
        if new_parent is None:
            self._id = 1

    ### PUBLIC METHODS ###

    def connect(self, outlet, other, inlet):
        connection = Connection(self, outlet, other, inlet)
        self._connections.append(connection)
        other._connections.append(connection)
        return connection

    def disconnect(self, connection):
        connection.target._connections.remove(connection)
        connection.source._connections.remove(connection)
